/***************************************************************************
 * The Open Armory API is a project to retrieve World of Warcraft(R) 
 * related XML data from The Armory.
 * 
 * The data retrieved via the Open Armory API from The Armory is 
 * proprietary to Blizzard Entertainment, Inc(R).
 * *************************************************************************
 * Copyright (C) 2009 - 2010 Tedla M.B. Brandsema
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ***************************************************************************/
package net.openarmory.core;

import java.util.List;

import net.openarmory.core.domain.ArmoryCharacterXmlWriter;
import net.openarmory.core.domain.ArmoryGuildXmlWriter;
import net.openarmory.core.domain.ArmoryImageWriter;
import net.openarmory.core.domain.ArmoryItemXmlWriter;
import net.openarmory.core.domain.constants.ArmoryCharacterDataType;
import net.openarmory.core.domain.constants.ArmoryDataType;
import net.openarmory.core.domain.constants.ArmoryGuildDataType;
import net.openarmory.core.domain.constants.ArmoryIconSize;
import net.openarmory.core.domain.constants.ArmoryImageType;
import net.openarmory.core.domain.constants.ArmoryPortraitLevel;
import net.openarmory.core.domain.constants.ArmoryZone;
import net.openarmory.core.domain.constants.CharacterClass;
import net.openarmory.core.domain.constants.CharacterGender;
import net.openarmory.core.domain.constants.CharacterRace;
import net.openarmory.core.domain.validation.RaceClassCombination;
import net.openarmory.core.domain.validation.Realm;
import net.openarmory.core.domain.validation.RealmStatusRetriever;

import org.apache.log4j.Logger;

// TODO: Auto-generated Javadoc
/**
 * <p>
 * This <b>Retrieve</b> class is the entry point to the Open Armory command-line
 * interface.
 * </p>
 * 
 * <p>
 * This class provides a means to retrieve XML data from The Armory via the
 * command-line.
 * </p>
 * 
 * 
 * @author Tedla M.B. Brandsema
 */
public final class Retrieve {

	/** The Constant LOG. */
	private static final Logger LOG = Logger.getLogger(Retrieve.class);

	/**
	 * <p>
	 * The main method is intended for passing command-line arguments.
	 * </p>
	 * 
	 * <p>
	 * Usage:
	 * </p>
	 * <ol>
	 * <li>
	 * <p>
	 * Retrieve character data (i.e.:profile, talents, reputation, achievements,
	 * statistics, arenateams, activityfeed):
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -r:&lt;realm&gt;
	 * -cn:&lt;character name&gt; -dt:&lt;datatype&gt;
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * Retrieve guild data (i.e.:guildroster, guildstats):
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -r:&lt;realm&gt;
	 * -g:&lt;guild&gt; -dt:&lt;datatype&gt;
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -r:&lt;realm&gt;
	 * -cn:&lt;character name&gt; -g:&lt;guild&gt; -dt:&lt;datatype&gt;
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * Retrieve character equipped item data:
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone> -i:&lt;itemId&gt; -r:&lt;realm&gt;
	 * -cn:&lt;charactername&gt; -s:&lt;slot&gt;
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * Retrieve item data:
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -i:&lt;itemId&gt;
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * Retrieve icon:
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -image:icon
	 * -size:&lt;21|43|64&gt; -name:&lt;icon name&gt;
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * Retrieve portrait:
	 * </p>
	 * <p>
	 * java -jar OpenArmory.jar -z:&lt;zone&gt; -image:portrait
	 * -level:&lt;80|70|60|default&gt; -gender:&lt;male|female&gt;
	 * -race:&lt;race&gt; -class:&lt;class&gt;
	 * </p>
	 * </li>
	 * </ol>
	 * <p>
	 * Options:
	 * </p>
	 * <ul>
	 * <li>
	 * <p>
	 * -z:EU|US
	 * </p>
	 * <p>
	 * Specify server zone
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -r:realm
	 * </p>
	 * <p>
	 * Specify character realm
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -cn:charactername
	 * </p>
	 * <p>
	 * Specify character name
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -g:guild
	 * </p>
	 * <p>
	 * Specify guild
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -dt:profile|talents|reputation|achievements|statistics|arenateams|
	 * activityfeed
	 * </p>
	 * <p>
	 * Specify data type
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -i:itemid
	 * </p>
	 * <p>
	 * Specify item id
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -s:slot
	 * </p>
	 * <p>
	 * Specify equipped slot of item (i.e.: head = 0, neck = 1, etc)
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -image:icon|portrait
	 * </p>
	 * <p>
	 * Specify the image type to retrieve
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -size:21|43|64
	 * </p>
	 * <p>
	 * Specify the icon size
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -name:icon name
	 * </p>
	 * <p>
	 * Specify the icon name
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -level:80|70|60|default
	 * </p>
	 * <p>
	 * Specify the portrait level
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -gender:male|female
	 * </p>
	 * <p>
	 * Specify character gender
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -race:Human|Orc|Dwarf|Night Elf|Undead|Tauren|Gnome|Troll|Blood
	 * Elf|Draenei
	 * </p>
	 * <p>
	 * Specify character race
	 * </p>
	 * </li>
	 * <li>
	 * <p>
	 * -class:Warrior|Paladin|Hunter|Rogue|Priest|Death
	 * Knight|Shaman|Mage|Warlock|Druid
	 * </p>
	 * <p>
	 * Specify character class
	 * </p>
	 * </li>
	 * </ul>
	 * 
	 * @param args
	 *            List of arguments supplied on the command line.
	 */
	public static void main(final String[] args) {
		(new Retrieve()).pullData(args);
	}

	/**
	 * <p>
	 * This method distills the relevant arguments from the command-line input
	 * </p>
	 * .
	 * 
	 * @param args
	 *            the command-line arguments
	 */
	public void pullData(final String[] args) {

		String zone = null;
		String realm = null;
		String characterName = null;
		String guild = null;
		String armoryDataType = null;
		String itemId = null;
		String slot = null;
		String image = null;
		String size = null;
		String iconName = null;
		String portraitLevel = null;
		String gender = null;
		String race = null;
		String clazz = null;

		if (args.length > 0) {

			for (int i = 0; i < args.length; i++) {

				if (args[i].charAt(0) == '-') {
					String option;
					String value = null;
					final int colon = args[i].indexOf(':');
					if ((colon > 0) && (colon < args[i].length() - 1)) {
						option = args[i].substring(1, colon);
						value = args[i].substring(colon + 1);
					} else {
						option = args[i].substring(1);
					}

					if (option.equals("z")) {
						zone = value;
					} else if (option.equals("r")) {
						realm = value;
					} else if (option.equals("cn")) {
						characterName = value;
					} else if (option.equals("g")) {
						guild = value;
					} else if (option.equals("dt")) {
						armoryDataType = value;
					} else if (option.equals("i")) {
						itemId = value;
					} else if (option.equals("s")) {
						slot = value;
					} else if (option.equals("image")) {
						image = value;
					} else if (option.equals("size")) {
						size = value;
					} else if (option.equals("name")) {
						iconName = value;
					} else if (option.equals("level")) {
						portraitLevel = value;
					} else if (option.equals("gender")) {
						gender = value;
					} else if (option.equals("race")) {
						race = value;
					} else if (option.equals("class")) {
						clazz = value;
					}
				}

			}

			validateArgs(zone, realm, characterName, guild, armoryDataType,
					itemId, slot, image, size, iconName, portraitLevel, gender,
					race, clazz);

		} else {
			badUsage("No arguments supplied.");
		}
	}

	/**
	 * Report incorrect usage of the command line, with a list of the options
	 * and arguments that are available.
	 * 
	 * @param message
	 *            The error message
	 */
	protected void badUsage(final String message) {
		if (!"".equals(message)) {
			System.out.println("\nError message: " + message + "\n");
		}
		System.out.println("Usage: ");
		System.out
				.println("\t1)\tRetrieve character data (i.e.:profile, talents, reputation, achievements, statistics, arenateams, activityfeed): ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -r:<realm> -cn:<character name> -dt:<datatype>");
		System.out
				.println("\t1)\tRetrieve guild data (i.e.:guildroster, guildstats): ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -r:<realm> -g:<guild> -dt:<datatype>");
		System.out.println("\t2)\tRetrieve character equipped item data: ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -i:<itemId> -r:<realm> -cn:<charactername> -s:<slot>");
		System.out.println("\t3)\tRetrieve item data: ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -i:<itemId>");
		System.out.println("\t4)\tRetrieve icon: ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -image:icon -size:<21|43|64> -name:<icon name>");
		System.out.println("\t5)\tRetrieve portrait: ");
		System.out
				.println("\t\tjava -jar OpenArmory.jar -z:<zone> -image:portrait -level:<80|70|60|default> -gender:<male|female> -race:<race> -class:<class>");
		System.out.println("Options: ");
		System.out.println("\t-z:EU|US\t\t\t\t\t\t\t\t\t\tSpecify server zone");
		System.out
				.println("\t-r:realm\t\t\t\t\t\t\t\t\t\tSpecify character realm");
		System.out
				.println("\t-cn:charactername\t\t\t\t\t\t\t\t\tSpecify character name");
		System.out.println("\t-g:guild\t\t\t\t\t\t\t\t\t\tSpecify guild");
		System.out
				.println("\t-dt:profile|talents|reputation|achievements|statistics|arenateams|activityfeed\t\tSpecify data type");
		System.out.println("\t-i:itemid\t\t\t\t\t\t\t\t\t\tSpecify item id");
		System.out
				.println("\t-s:slot\t\t\t\t\t\t\t\t\t\t\tSpecify equiped slot of item (i.e.: head = 0, neck = 1, etc)");
		System.out
				.println("\t-image:icon|portrait\t\t\t\t\t\t\t\t\tSpecify the image type to retrieve");
		System.out
				.println("\t-size:21|43|64\t\t\t\t\t\t\t\t\t\tSpecify the icon size");
		System.out
				.println("\t-name:icon name\t\t\t\t\t\t\t\t\t\tSpecify the icon name");
		System.out
				.println("\t-level:80|70|60|default\t\t\t\t\t\t\t\t\tSpecify the portrait level");
		System.out
				.println("\t-gender:male|female\t\t\t\t\t\t\t\t\tSpecify character gender");
		System.out
				.println("\t-race:Human|Orc|Dwarf|Night Elf|Undead|Tauren|Gnome|Troll|Blood Elf|Draenei\t\tSpecify character race");
		System.out
				.println("\t-class:Warrior|Paladin|Hunter|Rogue|Priest|Death Knight|Shaman|Mage|Warlock|Druid\tSpecify character class");

		System.exit(0);
	}

	/**
	 * Validates the command-line arguments.
	 * 
	 * @param zone
	 *            The zone where the realm resides (i.e. EU for Europe and US
	 *            for the United States of America)
	 * @param realm
	 *            The realm on which the character resides.
	 * @param characterName
	 *            The character name.
	 * @param guild
	 *            The guild on the specified realm.
	 * @param armoryDataType
	 *            The data type to be retrieved from The Armory.
	 * @param itemId
	 *            The id of the item to be retrieved.
	 * @param slot
	 *            The slot where the item is equipped by the character.
	 * @param image
	 *            The image type to retrieve
	 * @param size
	 *            The icon size
	 * @param iconName
	 *            The name of the icon to retrieve
	 * @param portraitLevel
	 *            The portrait level to retrieve
	 * @param gender
	 *            The character gender
	 * @param race
	 *            The character race
	 * @param clazz
	 *            The character class
	 */
	private void validateArgs(final String zone, final String realm,
			final String characterName, final String guild,
			final String armoryDataType, final String itemId,
			final String slot, final String image, final String size,
			final String iconName, final String portraitLevel,
			final String gender, final String race, final String clazz) {
		if (zone == null) {
			badUsage("Argument '-z:<zone>' can not be empty.");
			// if ZONE argument is valid
		} else if ((zone != null) && (armoryZoneValidation(zone) != null)) {
			if (((itemId == null) && (armoryDataType == null) && (image == null))
					|| ((itemId != null) && (armoryDataType != null) && (image != null))) {
				badUsage("Arguments '-dt:<datatype>' or '-i:<itemId>' or '-image:<icon|portrait>' must be supplied.");
				// if ITEMID argument is supplied
			} else if (itemId != null) {
				if (((realm != null) && (characterName == null))
						|| ((realm == null) && (characterName != null))) {
					badUsage("Both '-r:<realm>' and '-cn:<character name>' arguments must be supplied.");
					// if both REALM and CHARACTERNAME are supplied, retrieve
					// character specific item
				} else if ((realm != null) && (characterName != null)) {
					if (realmValidation(armoryZoneValidation(zone), realm)) {
						(new ArmoryItemXmlWriter())
								.writeCharacterSpecificItemTooltipXml(
										armoryZoneValidation(zone),
										Integer.parseInt(itemId), realm,
										characterName, Integer.parseInt(slot));
					} else {
						badUsage("The value of argument '-r:" + realm
								+ "' is not a valid realm for zone '-z:" + zone
								+ "'.");
					}
					// else retrieve an non character specific item
				} else if ((realm == null) && (characterName == null)) {
					(new ArmoryItemXmlWriter()).writeItemTooltipXml(
							armoryZoneValidation(zone),
							Integer.parseInt(itemId));
				}
				// if AROMORYDATATYPE argument is supplied
			} else if (armoryDataType != null) {
				// realm and zone must be supplied in order to retrieve
				// character or guild data types!
				if (realm == null) {
					badUsage("The '-r:<realm>' argument must be supplied.");
				}
				// validate the armory data type
				// and see if it is a character data type or a guild data type
				final ArmoryDataType adt = armoryDataTypeValidation(armoryDataType);
				final ArmoryGuildDataType agdt = armoryGuildDataTypeEquivalent(adt);
				final ArmoryCharacterDataType acdt = armoryCharacterDataTypeEquivalent(adt);
				if (agdt != null) {
					// check that the -g: argument (guild) is supplied.
					if ((guild != null) && !guild.isEmpty()) {
						// guild related retrieval
						if (characterName == null) {
							(new ArmoryGuildXmlWriter()).writeGuildXml(
									armoryZoneValidation(zone), realm, guild,
									agdt);
						} else {
							(new ArmoryGuildXmlWriter())
									.writeCharacterGuildXml(
											armoryZoneValidation(zone), realm,
											characterName, guild, agdt);
						}
					} else {
						badUsage("The value of argument '-g:"
								+ guild
								+ "' must be supplied in order to retrieve '-dt:"
								+ armoryDataType + "'.");
					}
				} else if (acdt != null) {
					// character related retrieval
					if (characterName == null) {
						badUsage("The '-cn:<character name>' argument must be supplied.");
					} else {
						if (realmValidation(armoryZoneValidation(zone), realm)) {
							(new ArmoryCharacterXmlWriter()).writeCharacterXml(
									armoryZoneValidation(zone), realm,
									characterName, acdt);
						} else {
							// FIXME: duplicate code
							badUsage("The value of argument '-r:" + realm
									+ "' is not a valid realm for zone '-z:"
									+ zone + "'.");
						}
					}
				} else {
					badUsage("The value of argument '-dt:" + armoryDataType
							+ "' is not a valid argument");
				}
				// if IMAGE argument is supplied
			} else if (image != null) {
				// if the IMAGE argument equals icon
				if (armoryImageValidation(image).equals(ArmoryImageType.ICON)) {
					if ((size == null) || (iconName == null)) {
						badUsage("Both '-size:<icon size>' and '-name:<icon name>' arguments must be supplied");
						// else retrieve an icon
					} else if ((size != null) && (iconName != null)) {
						(new ArmoryImageWriter()).writeIcon(
								armoryZoneValidation(zone),
								armoryIconSizeValidation(size), iconName);
					}
					// if the IMAGE argument equals portrait
				} else if (armoryImageValidation(image).equals(
						ArmoryImageType.PORTRAIT)) {
					if ((portraitLevel == null) || (gender == null)
							|| (race == null) || (clazz == null)) {
						badUsage("The arguments '-level:<portrait level>', '-gender:<character gender>', '-race:<character race>' and '-class:<character class>' must be supplied.");
					} else if ((portraitLevel != null) && (gender != null)
							&& (race != null) && (clazz != null)) {
						final CharacterRace characterRace = raceValidation(race);
						final CharacterClass characterClass = clazzValidation(clazz);
						if (RaceClassCombination.validateRaceClassCombination(
								characterRace, characterClass)) {
							(new ArmoryImageWriter())
									.writePortrait(
											armoryZoneValidation(zone),
											armoryPortraitLevelValidation(portraitLevel),
											genderValidation(gender),
											raceValidation(race),
											clazzValidation(clazz));
						} else {
							badUsage("The race class combination of "
									+ characterRace.toString() + " and "
									+ characterClass.toString()
									+ " is not valid.");
						}
					}
				}
			}
		} else {
			badUsage("The value of argument '-z:'" + zone
					+ " is not a valid zone.\n Choose one of: EU, US.");
		}
	}

	/**
	 * Validates the value of the command-line zone (-z:&lt;value&gt;) argument.
	 * 
	 * @param zone
	 *            A String value representing the armory zone
	 * 
	 * @return the armory zone
	 */
	private ArmoryZone armoryZoneValidation(final String zone) {

		final ArmoryZone[] armoryZones = ArmoryZone.values();

		for (final ArmoryZone armoryZone : armoryZones) {
			if (armoryZone.getConsoleParameterValue().equalsIgnoreCase(zone)) {
				return armoryZone;
			}
		}

		badUsage("The value of argument '-z:" + zone
				+ "' is not a valid zone.\nChoose one of: "
				+ ArmoryZone.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line data type (-dt:&lt;value&gt;)
	 * argument.
	 * 
	 * @param dataType
	 *            A String value representing the armory data type
	 * 
	 * @return the armory data type
	 */
	private ArmoryDataType armoryDataTypeValidation(final String dataType) {

		final ArmoryDataType[] armoryDataTypes = ArmoryDataType.values();

		for (final ArmoryDataType armoryDataType : armoryDataTypes) {
			if (armoryDataType.getConsoleParameterValue().equalsIgnoreCase(
					dataType)) {
				return armoryDataType;
			}
		}
		badUsage("The value of argument '-dt:" + dataType
				+ "' is not a valid data type.\nChoose one of: "
				+ ArmoryDataType.getStringValues() + ".");
		return null;
	}

	/**
	 * Armory guild data type equivalent.
	 * 
	 * @param armoryDataType
	 *            the armory data type
	 * @return the armory guild data type
	 */
	private ArmoryGuildDataType armoryGuildDataTypeEquivalent(
			final ArmoryDataType armoryDataType) {
		final ArmoryGuildDataType[] guildDataTypes = ArmoryGuildDataType
				.values();
		for (final ArmoryGuildDataType guildDataType : guildDataTypes) {
			if (guildDataType.getConsoleParameterValue().equals(
					armoryDataType.getConsoleParameterValue())) {
				return guildDataType;
			}
		}

		return null;
	}

	/**
	 * Armory character data type equivalent.
	 * 
	 * @param armoryDataType
	 *            the armory data type
	 * @return the armory character data type
	 */
	private ArmoryCharacterDataType armoryCharacterDataTypeEquivalent(
			final ArmoryDataType armoryDataType) {
		final ArmoryCharacterDataType[] characterDataTypes = ArmoryCharacterDataType
				.values();
		for (final ArmoryCharacterDataType characterDataType : characterDataTypes) {
			if (characterDataType.getConsoleParameterValue().equals(
					armoryDataType.getConsoleParameterValue())) {
				return characterDataType;
			}
		}

		return null;
	}

	/**
	 * Validates the value of the command-line data type (-image:&lt;value&gt;)
	 * argument.
	 * 
	 * @param image
	 *            the image
	 * @return the armory image type
	 */
	private ArmoryImageType armoryImageValidation(final String image) {

		final ArmoryImageType[] armoryImageTypes = ArmoryImageType.values();

		for (final ArmoryImageType armoryImageType : armoryImageTypes) {
			if (armoryImageType.getConsoleParameterValue().equalsIgnoreCase(
					image)) {
				return armoryImageType;
			}
		}

		badUsage("The '-image:" + image
				+ "' is not a valid image type.\nChoose one of: "
				+ ArmoryImageType.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line icon size (-size:&lt;value&gt;)
	 * argument.
	 * 
	 * @param iconSize
	 *            the icon size
	 * @return the armory icon size
	 */
	private ArmoryIconSize armoryIconSizeValidation(final String iconSize) {

		final ArmoryIconSize[] armoryIconSizes = ArmoryIconSize.values();

		for (final ArmoryIconSize armoryIconSize : armoryIconSizes) {
			if (armoryIconSize.getConsoleParameterValue().equalsIgnoreCase(
					iconSize)) {
				return armoryIconSize;
			}
		}

		badUsage("The value of argument '-size:" + iconSize
				+ "' is not a valid icon size.\nChoose one of: "
				+ ArmoryIconSize.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line portrait level
	 * (-level:&lt;value&gt;) argument.
	 * 
	 * @param portraitLevel
	 *            the portrait level
	 * @return the armory portrait level
	 */
	private ArmoryPortraitLevel armoryPortraitLevelValidation(
			final String portraitLevel) {

		final ArmoryPortraitLevel[] armoryPortraitLevels = ArmoryPortraitLevel
				.values();

		for (final ArmoryPortraitLevel armoryPortraitLevel : armoryPortraitLevels) {
			if (armoryPortraitLevel.getConsoleParameterValue()
					.equalsIgnoreCase(portraitLevel)) {
				return armoryPortraitLevel;
			}
		}

		badUsage("The value of argument '-level:" + portraitLevel
				+ "' is not a valid portait level.\nChoose one of: "
				+ ArmoryPortraitLevel.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line gender (-gender:&lt;value&gt;)
	 * argument.
	 * 
	 * @param gender
	 *            the gender
	 * @return the gender
	 */
	private CharacterGender genderValidation(final String gender) {

		final CharacterGender[] characterGenders = CharacterGender.values();

		for (final CharacterGender characterGender : characterGenders) {
			if (characterGender.getConsoleParameterValue().equalsIgnoreCase(
					gender)) {
				return characterGender;
			}
		}

		badUsage("The value of argument '-gender:" + gender
				+ "' is not a valid gender.\nChoose one of: "
				+ CharacterGender.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line race (-race:&lt;value&gt;)
	 * argument.
	 * 
	 * @param race
	 *            the race
	 * @return the race
	 */
	private CharacterRace raceValidation(final String race) {

		final CharacterRace[] characterRaces = CharacterRace.values();

		for (final CharacterRace characterRace : characterRaces) {
			if (characterRace.getConsoleParameterValue().equalsIgnoreCase(race)) {
				return characterRace;
			}
		}

		badUsage("The value of '-race:" + race
				+ "' is not a valid race.\nChoose one of: "
				+ CharacterRace.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line class (-class:&lt;value&gt;)
	 * argument.
	 * 
	 * @param clazz
	 *            the clazz
	 * @return the clazz
	 */
	private CharacterClass clazzValidation(final String clazz) {

		final CharacterClass[] characterClasses = CharacterClass.values();

		for (final CharacterClass characterClass : characterClasses) {
			if (characterClass.getConsoleParameterValue().equalsIgnoreCase(
					clazz)) {
				return characterClass;
			}
		}

		badUsage("The value of '-class:" + clazz
				+ "' is not a valid class.\nChoose one of: "
				+ CharacterClass.getStringValues() + ".");
		return null;
	}

	/**
	 * Validates the value of the command-line realm (-r:&lt;value&gt;)
	 * argument.
	 * 
	 * @param zone
	 *            The zone on where the realm resides (i.e. EU for Europe and US
	 *            for the United States of America)
	 * @param realm
	 *            The realm on which the character resides.
	 * 
	 * @return true, if successful
	 */
	private boolean realmValidation(final ArmoryZone zone, final String realm) {
		boolean realmIsValid = false;
		// For API implementation: create a singleton that sits on the container
		// that instantiates/renews itself periodically and saves the realms in
		// a bean
		final RealmStatusRetriever rsr = new RealmStatusRetriever();
		final List<Realm> rsList = rsr.retrieveRealms();
		for (int i = 0; i < rsList.size(); i++) {
			if (rsList.get(i).getZone().equalsIgnoreCase(zone.toString())
					&& rsList.get(i).getServer().equalsIgnoreCase(realm)) {
				realmIsValid = true;
				return realmIsValid;
			}
		}
		return realmIsValid;
	}
}
